-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RSDK-4089: use viam image #567
RSDK-4089: use viam image #567
Conversation
Warning your change may break code samples. If your change modifies any of the following functions please contact @viamrobotics/fleet-management. Thanks!
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, a couple small things but otherwise looks good to me!
I'm leaving this un-approved for now however because I believe (based on earlier conversation with @njooma) that we don't want to merge this into main
but rather into a separate release branch 3 or 4 cycles from now, so that we give people plenty of time to prepare for the breaking change.
src/viam/media/utils.py
Outdated
NotSupportedError: Raised if given an image that is not of MIME type `image/vnd.viam.dep`. | ||
""" | ||
if image.mime_type not in [CameraMimeType.JPEG, CameraMimeType.PNG, CameraMimeType.VIAM_RGBA]: | ||
NotSupportedError("Type must be `image/jpeg`, `image/png`, or `image/vnd.viam.rgba` to use get_image_dimensions()") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to raise
this error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wrote this whole paragraph why I thought having this error was necessary. And then realized you quite literally meant "hey, you forgot a raise
keyword". 🤦
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for reminding me I should be writing tests to make sure an error is raised if someone tries to call this function with the wrong mime type!
src/viam/media/utils.py
Outdated
return depth_arr_2d | ||
|
||
|
||
def get_image_dimensions(image: ViamImage) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(minor) When I see a method named get_foo
I typically expect that it will return a foo
, I think it's a bit strange that this returns None
. But it'd be weird to name it set_image_dimensions
too because it's taking no image_dimension
arguments! Can we rename to determine_image_dimensions
or something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is a very good point!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work so far! This is looking good
src/viam/components/camera/client.py
Outdated
def get_image_from_response(data: bytes, response_mime_type: str, request_mime_type: str) -> ViamImage: | ||
if not request_mime_type: | ||
request_mime_type = response_mime_type | ||
mime_type, is_lazy = CameraMimeType.from_lazy(request_mime_type) | ||
if is_lazy or mime_type._should_be_raw: | ||
image = RawImage(data=data, mime_type=response_mime_type) | ||
return image | ||
return Image.open(BytesIO(data), formats=LIBRARY_SUPPORTED_FORMATS) | ||
mime_type = CameraMimeType.from_string(request_mime_type) | ||
return ViamImage(data, mime_type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is not needed anymore and is actually incorrect. We should just move this to the get_image
function:
request = ...
response: GetImageResponse = await self.client.GetImage(request, timeout=timeout)
return ViamImage(response.image, response.mime_type)
if not request.mime_type: | ||
if camera.name not in self._camera_mime_types: | ||
self._camera_mime_types[camera.name] = CameraMimeType.JPEG | ||
|
||
request.mime_type = self._camera_mime_types[camera.name] | ||
|
||
response = GetImageResponse(mime_type=request.mime_type, image=image.data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We actually don't need any of this anymore -- this was useful when we were encoding images. But because we're not doing that anymore, just sending raw bytes back, we should actually use the mime type returned from the camera (image.mime_type
) instead of request.mime_type
finally: | ||
image.close() | ||
response = HttpBody(data=img, content_type=image.mime_type if isinstance(image, RawImage) else mimetype) # type: ignore | ||
response = HttpBody(data=image.data, content_type=image.mime_type if isinstance(image, ViamImage) else mimetype) # type: ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This long check isn't needed anymore since image
CAN ONLY ever be ViamImage
. We can also remove the try/except
block that attempts to get the mimetype.
src/viam/media/utils.py
Outdated
Returns: | ||
List[List[int]]: The standard representation of the image. | ||
""" | ||
if image.mime_type != CameraMimeType.VIAM_RAW_DEPTH.value: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need the .value
at the end of CameraMimeType.VIAM_RAW_DEPTH.value
(but I'm not 100% sure)
src/viam/media/video.py
Outdated
@@ -159,10 +56,10 @@ class ViamImage: | |||
Provides the raw data and the mime type, as well as lazily loading and caching the PIL.Image representation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment needs to be updated to remove the PIL
reference
src/viam/media/video.py
Outdated
def width(self) -> Union[int, None]: | ||
"""The width of the image""" | ||
return self._width |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Continuing from my earlier comment around keeping the _image
and _image_decoded
properties, the width
and height
getters should now be something like:
# First, check if we already have a value
if self._width is not None:
return self._width
# If we don't have a value, check to see if we have already tried to decode the image
# If we have not, then try to decode the image now
if not self._image_decoded:
try:
self._image = Image.open(BytesIO(self.data), formats=LIBRARY_SUPPORTED_FORMATS)
except UnidentifiedImageError:
self._image = None
self._image_decoded = True
# If we have decoded the image and the image is not none, then set the width so we don't have to do this again
if self._image_decoded and self._image is not None:
self._width = self._image.width
return self._width
src/viam/services/vision/vision.py
Outdated
# Get image dimensions | ||
determine_image_dimensions(img) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this -- the user should never be calling this
src/viam/services/vision/vision.py
Outdated
# Get image dimensions | ||
determine_image_dimensions(img) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above -- the user should never be calling this
tests/test_media.py
Outdated
img.close() | ||
assert img._mime_type == CameraMimeType.PNG | ||
pil_img = viam_to_pil_image(img) | ||
assert pil_img.tobytes() == i.tobytes() | ||
|
||
def test_mime_type_update(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't allow users to update mime types anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor update to the comments, but otherwise this is great
src/viam/components/camera/camera.py
Outdated
Be sure to close the image when finished. | ||
|
||
NOTE: If the mime type is ``image/vnd.viam.dep`` you can use :func:`viam.media.video.ViamImage.bytes_to_depth_array` | ||
NOTE: If the mime type is ``image/vnd.viam.dep`` you can use :func:`viam.media.utils.bytes_to_depth_array` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Revert this comment change, as bytes_to_depth_array
is on ViamImage
BREAKING CHANGE!!!!
Please note that this is going to be merged into
rc-0.21.0
to give time for the community to get used to the changes.Jira Ticket
Changes:
ViamImage
when calling `camera.get_image()ViamImage
for the vision serviceCameraMimeType
functions and lazy conceptPIL.Image
from the Python SDK (barring image examples and helper functions)media/utils
file to contain helper functionsViamImage
toPIL.Image
and getting image dimensionsTesting:
Tested using a webcam and called both
get_image_dimensions()
as well asviam_to_pil_image()
.